Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useful functions for external use of WASI filesystem #595

Merged
merged 4 commits into from
Jul 31, 2019

Conversation

MarkMcCaskey
Copy link
Contributor

@MarkMcCaskey MarkMcCaskey commented Jul 30, 2019

part of #583

@MarkMcCaskey MarkMcCaskey added the 📦 lib-wasi About wasmer-wasi label Jul 30, 2019
@MarkMcCaskey MarkMcCaskey mentioned this pull request Jul 30, 2019
4 tasks
pub fn close(self) {}
/// This trait relies on your file closing when it goes out of scope via `Drop`
/// it does not require `Drop` because `std::fs::File` does not implement it
/// (TODO: figure out how that makes sense, because it clearly does)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::fs::File does not implement Drop, because it contains a std::sys::fs::File, which does not implement Drop as it contains a std::sys::fd::FileDesc, which implements Drop.

aka, only the innermost item needs to implement Drop, rust figures out the rest on it's own?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I was reading through the code, but didn't get that far -- that's good to know

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, yeah, apparently we should (almost?) never require an impl of Drop, because of the above.


#[derive(Debug)]
pub struct Stdout(std::io::Stdout);
impl Read for Stdout {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like a 'nicer' way of doing this is to essentially encapsulate Read/Write/Seek in our trait, and provide default generic implementations if the type implements Read/Write/Seek.

(this is probably not nicer in many other ways, so meh.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeah, I see what you mean. I think this is fine because while it is garbage code, we only need to write it once -- and I'll refactor the state.rs file to hide things like this because we mostly never need to see it -- and it lets us use all code working with the standard traits including third party libraries which could save us a lot of time in the future.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, so does this approach. The issue (either way, really) is that if a third party library is missing any one of these three, you have to wrap it in a newtype and create dummy implementations. At least with the 'wrapper trait' approach, you aren't implementing, say, Seek on something that can't actually support Seek. shrug

only solution I can think of that doesn't require boilerplate is probably 'wrapper trait' + specialization, and even then a) i don't think we want to do that and b) it doesn't appear to work like it does in my head so...

@kitlith
Copy link

kitlith commented Jul 30, 2019

I will note that currently this PR by itself does not expose any extra functionality, as WasiFs/WasiState and such is still not exported at the crate top-level.

EDIT: now it does.

@MarkMcCaskey
Copy link
Contributor Author

@kitlith
Let me know if it looks good to you

specifically,

/// Get WasiState from a Ctx
pub unsafe fn get_wasi_state(ctx: &mut Ctx) -> &mut WasiState {
    &mut *(ctx.data as *mut WasiState)
}

Presumably in the future we can also provide higher level APIs that don't require using the raw WASI types which I also exported in this PR. I wrapped the error type for the public facing APIs and maybe we can do the same with permissions and capabilities as well. The fd capabilities should map very closely to what std::file::OpenOptions is doing, so a similar builder pattern should be simple to implement

@MarkMcCaskey
Copy link
Contributor Author

bors r+

bors bot added a commit that referenced this pull request Jul 31, 2019
595: Add useful functions for external use of WASI filesystem r=MarkMcCaskey a=MarkMcCaskey

part of #583 

Co-authored-by: Mark McCaskey <[email protected]>
Co-authored-by: Mark McCaskey <[email protected]>
@MarkMcCaskey
Copy link
Contributor Author

bors r-

@bors
Copy link
Contributor

bors bot commented Jul 31, 2019

Canceled

@MarkMcCaskey
Copy link
Contributor Author

MarkMcCaskey commented Jul 31, 2019

I updated the plugin example to use the new logging feature. It relies on the guest calling into the host. I think we will probably definitely need the builder pattern, too. Because relying on the guest to do that is less than ideal. There's also the possibility of solving this problem with Wasm transformations (the host performing arbitrary modifications to the Guest's Wasm before running) but I don't think that's something we support very well right now

@MarkMcCaskey
Copy link
Contributor Author

bors r+

bors bot added a commit that referenced this pull request Jul 31, 2019
595: Add useful functions for external use of WASI filesystem r=MarkMcCaskey a=MarkMcCaskey

part of #583 

Co-authored-by: Mark McCaskey <[email protected]>
Co-authored-by: Mark McCaskey <[email protected]>
@bors bors bot merged commit b407633 into master Jul 31, 2019
@bors bors bot deleted the feature/public-api-wasi-fs branch July 31, 2019 04:12
@kitlith
Copy link

kitlith commented Jul 31, 2019

I don't really see why the guest needs to call into the host, when there's wasmer_runtime::Instance::context_mut? I may be missing something.

And I don't think get_wasi_state should have been changed into a safe function, as it is only sound if the Ctx came from your WASI implementation, right? We (currently) must rely on the user to know this...

@MarkMcCaskey
Copy link
Contributor Author

@kitlith Wow, I did not know about that at all, but it makes sense that that would exist. That would actually be useful in a personal project I'm making with Wasmer. Thanks! I'll update the example.

Hmm, that's a fair point.

So the reason why I made it safe was because in our code we're casting a &Ctx to a &mut Ctx, which is definitely not safe... here I made it require a &mut Ctx so it's safe in that regard, but you're correct, calling this on a non-wasi context will do bad things and have undefined behavior. I'll update the example and make it unsafe in a PR before we release tomorrow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 lib-wasi About wasmer-wasi
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants